package org.lex.utils.pool;

import java.util.Iterator;
import java.util.Stack;

public class StackPool<T> extends AbstractPool<T> {
	protected Stack<T> pool = null;
	private int maxIdleNumber = DEFAULT_IDLE_NUMBER;
	private int activeCount = 0;

	public StackPool() {
		this(null, DEFAULT_IDLE_NUMBER);
	}

	public StackPool(int maxIdle) {
		this(null, maxIdle);
	}

	public StackPool(ObjectFactory<T> factory) {
		this(factory, DEFAULT_IDLE_NUMBER);
	}

	public StackPool(ObjectFactory<T> factory, int maxIdle) {
		this.setFactory(factory);
		maxIdleNumber = (maxIdle < 0 ? DEFAULT_IDLE_NUMBER : maxIdle);
		pool = new Stack<T>();
	}

	public synchronized T get() {
		assertOpen();
		assertFactory();
		T obj = null;
		while (null == obj) {
			if (false == pool.empty())
				obj = pool.pop();
			else
				obj = getFactory().create();

			if (null != obj) {
				getFactory().prepare(obj);
				if (false == getFactory().isReuseable(obj)) {
					getFactory().destroy(obj);
					obj = null;
				}
			}
		}
		activeCount++;
		return obj;
	}

	public synchronized void put(T obj) {
		assertOpen();
		assertFactory();
		if (false == getFactory().isReuseable(obj) || false == getFactory().clean(obj)) {
			// obj��������ʹ�û�������ʧ�ܣ��轫�����
			getFactory().destroy(obj);
			obj = null;
			activeCount--;
			notifyAll();
			return;
		}

		if (pool.size() >= maxIdleNumber)
			getFactory().destroy(pool.pop());
		else
			pool.push(obj);
		activeCount--;
		notifyAll();
		return;
	}

	public synchronized int getPoolSize() {
		assertOpen();
		return pool.size() + activeCount;
	}

	public synchronized int getActiveCount() {
		assertOpen();
		return activeCount;
	}

	public synchronized void clear() {
		assertOpen();
		assertFactory();
		Iterator<T> it = pool.iterator();
		while (it.hasNext())
			getFactory().destroy(it.next());
		pool.clear();
	}

	public synchronized void close() {
		clear();
		pool = null;
		this.setFactory(null);
		super.close();
	}
}
